#pragma once

#include "htmlayout.h"
#include "htmlayout_behavior.h"
#include "htmlayout_dom.hpp"
#include "behaviors/notifications.h"


// CHTMLayoutCtrl

bool GetHtmlResource(LPCTSTR pszName, /*out*/PBYTE& pb, /*out*/DWORD& cb, HMODULE hModule);

class CHTMLayoutCtrl : public CWnd
{
  DECLARE_DYNAMIC(CHTMLayoutCtrl)

public:
  CHTMLayoutCtrl();
  virtual ~CHTMLayoutCtrl();

protected:
  DECLARE_MESSAGE_MAP()

public:
  // Generic creator
  virtual BOOL Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID);

  // Generic creator allowing extended style bits
  virtual BOOL CreateEx(DWORD dwExStyle, DWORD dwStyle, const RECT& rect,
    CWnd* pParentWnd, UINT nID);

  // Load html from memory buffer
  bool LoadHtml(LPCBYTE pb, DWORD nBytes)
  {
    ASSERT(::IsWindow(m_hWnd));
    return ::HTMLayoutLoadHtml(m_hWnd, pb, nBytes) != 0;
  }

  // load html from resource by name
  bool LoadHtmlResource(LPCTSTR pszName, HMODULE hModule = NULL);
  // load html from resource by id
  bool LoadHtmlResource(DWORD resID, HMODULE hModule = NULL);

  // Overridables
  
  // custom behavior notifications, see behaviors/notifications.h
  virtual LRESULT OnBehaviorNotify(UINT uMsg, WPARAM wParam, LPARAM lParam);

  // non-HTMLayout notifications
  virtual LRESULT OnHtmlGenericNotifications(UINT uMsg, WPARAM wParam, LPARAM lParam);
  
  // create control for <INPUT>, <WIDGET>, <TEXTAREA>, <SELECT>
  virtual LRESULT OnCreateControl(LPNMHL_CREATE_CONTROL pnmcc);
  
  // post-control-creation notification. Good place to set additional styles for builtin controls
  virtual LRESULT OnControlCreated(LPNMHL_CREATE_CONTROL pnmcc);

  // your chance to destroy child control in your own way. ::DestroyWindow used by default
  virtual LRESULT OnDestroyControl(LPNMHL_DESTROY_CONTROL pnmhl);

  // All hyperlink notifications generated by the hyperlink behavior.
  virtual LRESULT OnHyperLink(NMHL_HYPERLINK* pnmhl);
    virtual LRESULT OnHyperLinkEnter(NMHL_HYPERLINK* pnmhl);
    virtual LRESULT OnHyperLinkLeave(NMHL_HYPERLINK* pnmhl);
    virtual LRESULT OnHyperLinkClick(NMHL_HYPERLINK* pnmhl);

  // Override this to load data (images or css sheets) from places other than this app resources.
  virtual LRESULT OnLoadData(LPNMHL_LOAD_DATA pnmld);
  
  // Data arrived. Handle this if you want to store them somewhere for future use.
  virtual LRESULT OnDataLoaded(LPNMHL_DATA_LOADED pnmld);
  
  // All resources are in place.
  virtual LRESULT OnDocumentComplete();
  
  // Attach your own behavior to the element
  virtual LRESULT OnAttachBehavior( LPNMHL_ATTACH_BEHAVIOR lpab );



// DOM helpers
  int     GetAttrInt(HELEMENT he, LPCSTR attrName, int defaultValue = 0);
  CString GetElementType(HELEMENT he);
  CString GetAttr(HELEMENT he, LPCSTR attrName);
  bool    HasAttr(HELEMENT he, LPCSTR attrName);

protected:

  // HTMLayout callback
  inline static LRESULT CALLBACK callback(UINT uMsg, WPARAM wParam, LPARAM lParam, LPVOID vParam)
  {
      ASSERT(vParam);
      CHTMLayoutCtrl* pThis = (CHTMLayoutCtrl*)vParam;
      return pThis->OnHtmlNotify(uMsg, wParam, lParam);
  }

  void SetCallback()
  {
    ASSERT(::IsWindow(m_hWnd));
    ::HTMLayoutSetCallback(m_hWnd,callback, this);
  }

  virtual BOOL PreTranslateMessage( MSG* pMsg )
  {
  if(pMsg->message == WM_CHAR)
  {
    BOOL bHandled = FALSE;
    ::HTMLayoutProcND( m_hWnd, pMsg->message, pMsg->wParam, pMsg->lParam, &bHandled);
    if(bHandled)
      return TRUE;
  }
  return CWnd::PreTranslateMessage(pMsg);

  }

  virtual LRESULT WindowProc( UINT message, WPARAM wParam, LPARAM lParam)
  {
    if(message == WM_BEHAVIOR_NOTIFY)
      return OnBehaviorNotify(message, wParam, lParam);
  /*if(message == WM_KEYDOWN || message == WM_KEYUP || message == WM_CHAR)
  {
    return ::HTMLayoutProc( m_hWnd, message, wParam, lParam);
  }*/

    return CWnd::WindowProc(message, wParam, lParam);
  }

  virtual LRESULT OnHtmlNotify(UINT uMsg, WPARAM wParam, LPARAM lParam)
  {
    ASSERT(uMsg == WM_NOTIFY);

    // Crack and call appropriate method
    
    // here are all notifiactions
    switch(((NMHDR*)lParam)->code) 
    {
      case HLN_CREATE_CONTROL:    return OnCreateControl((LPNMHL_CREATE_CONTROL) lParam);
      case HLN_CONTROL_CREATED:   return OnControlCreated((LPNMHL_CREATE_CONTROL) lParam);
      case HLN_DESTROY_CONTROL:   return OnDestroyControl((LPNMHL_DESTROY_CONTROL) lParam);
      case HLN_LOAD_DATA:         return OnLoadData((LPNMHL_LOAD_DATA) lParam);
      case HLN_DATA_LOADED:       return OnDataLoaded((LPNMHL_DATA_LOADED)lParam);
      case HLN_DOCUMENT_COMPLETE: return OnDocumentComplete();
      case HLN_ATTACH_BEHAVIOR:   return OnAttachBehavior((LPNMHL_ATTACH_BEHAVIOR)lParam );
    }
    return OnHtmlGenericNotifications(uMsg,wParam,lParam);
  }

  virtual LRESULT OnHtmlCommand(NMHL_COMMAND_CLICK *pnmCommand) 
  {
    //empty placeholder
    return 0;
  }

  LRESULT LoadResourceData(LPNMHL_LOAD_DATA pnmld);

};

// HTML command map macros:
#define BEGIN_HTML_COMMAND_MAP \
        virtual LRESULT OnHtmlCommand(NMHL_COMMAND_CLICK *pnmCommand) {

#define ON_HTML_COMMAND(WStrHtmlElementId, Proc) \
        if( wcscmp(WStrHtmlElementId,pnmCommand->szElementID) == 0 ) \
        {  Proc(); return 0; }

#define END_HTML_COMMAND_MAP \
        return 0; }

#pragma comment(lib, "HTMLayout.lib")

